package cn.stronglink.esm27.collection.iot.devices.esm27;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.TooManyListenersException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;

import cn.stronglink.esm27.collection.iot.devices.esm27.response.ESM27ServerListener;
import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;

/**
 * ESM27服务
 *
 * @author yuzhantao
 *
 */
@Service("esm27Server")
public class ESM27Server implements ApplicationListener<ApplicationEvent> {
//	private final static Logger logger = LogManager.getLogger(ESM27Server.class.getName());

	private ESM27ServerListener listener;
	// 输入输出流
	private InputStream inputStream;
	private OutputStream outputStream;

	protected CommPortIdentifier portIdentifier;
	protected CommPort commPort;

	/**
	 * 端口名
	 */
	private String serialPortName;
	/**
	 * 端口号
	 */
	private int serialPortBaudRate = 9600;

	@Value("${weather.protocol.version}")
	private Integer protocolVersion;

	public ESM27Server() {
	}

	public String getSerialPortName() {
		return serialPortName;
	}

	public void setSerialPortName(String serialPortName) {
		this.serialPortName = serialPortName;
	}

	public int getSerialPortBaudRate() {
		return serialPortBaudRate;
	}

	public void setSerialPortBaudRate(int serialPortBaudRate) {
		this.serialPortBaudRate = serialPortBaudRate;
	}

	/**
	 * 初始化串口
	 *
	 * @throws NoSuchPortException
	 * @throws PortInUseException
	 * @throws UnsupportedCommOperationException
	 * @throws TooManyListenersException
	 * @throws IOException
	 */
	@SuppressWarnings("unused")
	public void openSerialPort() throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException,
			TooManyListenersException, IOException {
		if (this.listener == null) {
			this.listener = new ESM27ServerListener(protocolVersion);
		}
		closeSerialPort();
		portIdentifier = CommPortIdentifier.getPortIdentifier(this.getSerialPortName());
		commPort = portIdentifier.open(this.getSerialPortName(), 5000);

		if (commPort instanceof SerialPort) {
			SerialPort serialPort = (SerialPort) commPort;
			// 设置串口参数（波特率，数据位8，停止位1，校验位无）baudRate
			serialPort.setSerialPortParams(this.getSerialPortBaudRate(), SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
					SerialPort.PARITY_NONE);
			serialPort.addEventListener(this.listener);
			serialPort.notifyOnDataAvailable(true);
			System.out.println("开启串口成功，串口名称：" + this.getSerialPortName());
			this.outputStream = serialPort.getOutputStream();
			this.inputStream = serialPort.getInputStream();
			this.listener.setInputStream(inputStream);
		}
	}

	/**
	 * 关闭串口
	 */
	public synchronized void closeSerialPort() {

		try {
			if (commPort != null) {
				SerialPort sp = (SerialPort) commPort;
				sp.notifyOnDataAvailable(false);
				sp.removeEventListener();

				try {
					if (this.outputStream != null) {
						this.outputStream.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				try {
					if (this.inputStream != null) {
						this.inputStream.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}

				sp.close();
				sp = null;
			}
			if (portIdentifier != null) {
				portIdentifier = null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取串口列表
	 *
	 * @return
	 */
	public List<String> getSerialPortList() {
		List<String> serialPortList = new ArrayList<>();
		@SuppressWarnings({ "unchecked", "static-access" })
		Enumeration<CommPortIdentifier> portList = portIdentifier.getPortIdentifiers();
		while (portList.hasMoreElements()) {
			CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
				serialPortList.add(portId.getName());
			}
		}

		return serialPortList;
	}

	/**
	 * 发送数据
	 *
	 * @param datas
	 * @throws IOException
	 */
	public synchronized void send(byte[] datas) throws IOException {
		if(outputStream!=null) {
			outputStream.write(datas);
			outputStream.flush();
		}
	}

	/**
	 * 是否链接
	 *
	 * @return
	 */
	public boolean isConnection() {
		return this.outputStream != null;
	}

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
//		try {
//			this.openSerialPort();
//		} catch (NoSuchPortException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (PortInUseException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (UnsupportedCommOperationException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (TooManyListenersException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		} catch (IOException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
	}
}
